package com.crm.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crm.crm.domain.BusinessPool;
import com.crm.crm.domain.CluePool;
import com.crm.crm.domain.RulePool;
import com.crm.crm.domain.SysNotice;
import com.crm.crm.mapper.BusinessPoolMapper;
import com.crm.crm.mapper.CluePoolMapper;
import com.crm.crm.mapper.NoticeMapper;
import com.crm.crm.mapper.RulePoolMapper;
import com.crm.crm.service.RuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.invoke.VarHandle;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class RuleServiceImpl extends ServiceImpl<RulePoolMapper, RulePool> implements RuleService {
    @Autowired
    private RulePoolMapper rulePoolMapper;

    @Autowired
    private CluePoolMapper cluePoolMapper;

    @Autowired
    private BusinessPoolMapper businessPoolMapper;

    @Autowired
    private NoticeMapper noticeMapper;


    @Override
    public void addOrUpdate(RulePool rulePool) {
        String type = rulePool.getType();
        LambdaQueryWrapper<RulePool> wrapper = new LambdaQueryWrapper<RulePool>().eq(RulePool::getType, type);
        RulePool rulePoolReturn = rulePoolMapper.selectOne(wrapper);
        if (rulePoolReturn == null) {
            rulePool.setCreateTime(LocalDateTime.now());
            rulePoolMapper.insert(rulePool);
        } else {
            Integer id = rulePoolReturn.getId();
            rulePool.setId(id);
            rulePoolMapper.deleteById(id);
            rulePoolMapper.insert(rulePool);
        }
    }

    @Override
    public RulePool getRulePool(Integer type) {
        LambdaQueryWrapper<RulePool> wrapper = new LambdaQueryWrapper<RulePool>().eq(RulePool::getType, type);
        RulePool rulePool = rulePoolMapper.selectOne(wrapper);
        //rulePoolMapper.
        return rulePool;
    }

    /**
     * 定时任务：线索回收
     */
    @Scheduled(cron = "0 0 0/1 * * ? ")
    //@Scheduled(cron = "0/20 * * * * ? ")
    public void recovery() {
        log.info("定时任务recovery开始执行，周期为每小时执行一次");
        //先查删除逻辑
        List<RulePool> rulePools = rulePoolMapper.selectList(null);
        for (RulePool rulePool : rulePools) {
            //去两个pool表里判断
            String type = rulePool.getType();
            Integer limitTime = rulePool.getLimitTime();
            String limitTimeType = rulePool.getLimitTimeType();
            if (type.equals("0")) {
                //type为0，对应线索池，判断是否超过时间，超过时间则删除
                LocalDateTime lastTime = computeLastTime(limitTime, limitTimeType, LocalDateTime.now(), 0);
                String formattedLastTime = lastTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (formattedLastTime == null) {
                    continue;
                }
                //判断数据库里时间小于formattedLastTime,删除
                log.info("线索池开始执行时间判断,判断时间早于{}的数据需执行删除操作", formattedLastTime);
                LambdaQueryWrapper<CluePool> wrapper = new LambdaQueryWrapper<CluePool>().lt(CluePool::getCreateTime, formattedLastTime);
                int deleteCount = cluePoolMapper.delete(wrapper);
                log.info("线索池匹配到{}条超过配置时间的数据，执行删除", deleteCount);
            } else {
                //type为1，对应商机池，判断是否超过时间，超过时间则删除
                LocalDateTime lastTime = computeLastTime(limitTime, limitTimeType, LocalDateTime.now(), 0);
                String formattedLastTime = lastTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                if (formattedLastTime == null) {
                    continue;
                }
                //判断数据库里时间小于formattedLastTime,删除
                log.info("公海池开始执行时间判断,判断时间早于{}的数据需执行删除操作", formattedLastTime);
                LambdaQueryWrapper<BusinessPool> wrapper = new LambdaQueryWrapper<BusinessPool>().lt(BusinessPool::getCreateTime, formattedLastTime);
                int deleteCount = businessPoolMapper.delete(wrapper);
                log.info("公海池匹配到{}条超过配置时间的数据，执行删除", deleteCount);
            }
        }
    }

    /**
     * 计算LastTime
     *
     * @param Time
     * @param TimeType
     * @param StartTime
     * @param Type      0为往前、1为往后
     */
    private LocalDateTime computeLastTime(Integer Time, String TimeType, LocalDateTime StartTime, Integer Type) {
        //LocalDateTime currentTime = LocalDateTime.now(); // 当前时间
        LocalDateTime lastTime;
        //判断计算类型
        if (Type == 0) {
            //判断时间类型
            switch (TimeType) {
                case "0":
                    // 时间单位为小时
                    lastTime = StartTime.minus(Time, ChronoUnit.HOURS);
                    break;
                case "1":
                    // 时间单位为天
                    lastTime = StartTime.minus(Time, ChronoUnit.DAYS);
                    break;
                case "2":
                    // 时间单位为周
                    lastTime = StartTime.minus(Time, ChronoUnit.WEEKS);
                    break;
                default:
                    log.info("时间类型错误,请检查数据库或数据字典");
                    return null;
            }
        } else {
            //判断时间类型
            switch (TimeType) {
                case "0":
                    // 时间单位为小时
                    lastTime = StartTime.plus(Time, ChronoUnit.HOURS);
                    break;
                case "1":
                    // 时间单位为天
                    lastTime = StartTime.plus(Time, ChronoUnit.DAYS);
                    break;
                case "2":
                    // 时间单位为周
                    lastTime = StartTime.plus(Time, ChronoUnit.WEEKS);
                    break;
                default:
                    log.info("时间类型错误,请检查数据库或数据字典");
                    return null;
            }
        }
        return lastTime;
    }

    /**
     * 定时任务：线索回收提醒
     */
    @Scheduled(cron = "0 0/30 * * * * ")
    //@Scheduled(cron = "0/20 * * * * ? ")
    public void recyclingReminders() {
        log.info("定时任务recyclingReminders开始执行，周期为每三十分钟执行一次");
        boolean flag = false;//标志，判断是否有新消息
        //查线索池\商机海配置
        List<RulePool> rulePools = rulePoolMapper.selectList(null);
        for (RulePool rulePool : rulePools) {
            String type = rulePool.getType();
            if (type.equals("0")) {
                //type为0，对应线索池，判断是否超过时间，超过时间则删除
                //先算出结束时间
                Integer limitTime = rulePool.getLimitTime();
                String limitTimeType = rulePool.getLimitTimeType();
                LocalDateTime lastTime = computeLastTime(limitTime, limitTimeType, LocalDateTime.now(), 0);
                //再往前推提前时间
                Integer warnTime = rulePool.getWarnTime();
                String warnTimeType = rulePool.getWarnTimeType();
                lastTime = computeLastTime(warnTime, warnTimeType, lastTime, 1);
                String formattedLastTime = lastTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

                //判断数据库里时间小于formattedLastTime,删除
                log.info("线索池开始执行时间判断,判断时间早于{}的数据需执行消息推送", lastTime);
                LambdaQueryWrapper<CluePool> wrapper = new LambdaQueryWrapper<CluePool>().lt(CluePool::getCreateTime, formattedLastTime).eq(CluePool::getHasNoticed, "0");
                List<CluePool> cluePools = cluePoolMapper.selectList(wrapper);
                ArrayList<String> names = new ArrayList<>();
                for (CluePool cluePool : cluePools) {
                    //发送消息
                    cluePool.setHasNoticed("1");
                    names.add(cluePool.getName());
                }
                int count = cluePoolMapper.delete(wrapper);
                cluePoolMapper.insert(cluePools);
                if (count > 0) {
                    log.info("线索池匹配到{}条超过配置时间的数据，执行消息推送", count);
                    SysNotice sysNotice = new SysNotice();
                    sysNotice.setCreateBy("system");
                    sysNotice.setNoticeTitle("线索回收提醒");
                    //开始拼接消息内容
                    StringBuilder noticeContent = new StringBuilder();
                    noticeContent.append("<p style=\"color: #e63946; font-size: 15px; font-weight: bold;\">请注意</p><p>线索池中,<span style=\"color: #e63946;\">");
                    for (String name : names) {
                        noticeContent.append(name + "、");
                    }
                    noticeContent.deleteCharAt(noticeContent.length() - 1);
                    noticeContent.append("</span>的数据<span style=\"color: #e63946;\">");
                    noticeContent.append(warnTime);
                    switch (warnTimeType) {
                        case "0":
                            noticeContent.append("小时后");
                            break;
                        case "1":
                            noticeContent.append("天后");
                            break;
                        case "2":
                            noticeContent.append("周后");
                            break;
                    }
                    noticeContent.append("</span>将被回收，届时将无法捞取,请注意筛查避免有用的数据被回收</p>");
                    sysNotice.setNoticeContent(noticeContent.toString());
                    sysNotice.setStatus("0");
                    sysNotice.setCreateTime(LocalDateTime.now());
                    noticeMapper.insert(sysNotice);
                    flag = true;
                }
            } else {
                //type为1，对应商机池，判断是否超过时间，超过时间则删除
                //先算出结束时间
                Integer limitTime = rulePool.getLimitTime();
                String limitTimeType = rulePool.getLimitTimeType();
                LocalDateTime lastTime = computeLastTime(limitTime, limitTimeType, LocalDateTime.now(), 0);
                //再往前推提前时间
                Integer warnTime = rulePool.getWarnTime();
                String warnTimeType = rulePool.getWarnTimeType();
                lastTime = computeLastTime(warnTime, warnTimeType, lastTime, 1);
                String formattedLastTime = lastTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

                //判断数据库里时间小于formattedLastTime,删除
                log.info("商机公海开始执行时间判断,判断时间早于{}的数据需执行消息推送", lastTime);
                LambdaQueryWrapper<BusinessPool> wrapper = new LambdaQueryWrapper<BusinessPool>().lt(BusinessPool::getCreateTime, formattedLastTime).eq(BusinessPool::getHasNoticed, "0");
                List<BusinessPool> businessPools = businessPoolMapper.selectList(wrapper);
                ArrayList<String> names = new ArrayList<>();
                for (BusinessPool businessPool : businessPools) {
                    //发送消息
                    businessPool.setHasNoticed("1");
                    names.add(businessPool.getName());
                }
                int count = businessPoolMapper.delete(wrapper);
                businessPoolMapper.insert(businessPools);
                if (count > 0) {
                    log.info("商机公海匹配到{}条超过配置时间的数据，执行消息推送", count);
                    SysNotice sysNotice = new SysNotice();
                    sysNotice.setCreateBy("system");
                    sysNotice.setNoticeTitle("商机回收提醒");
                    //开始拼接消息内容
                    StringBuilder noticeContent = new StringBuilder();
                    noticeContent.append("<p style=\"color: #e63946; font-size: 15px; font-weight: bold;\">请注意</p><p>商机公海中,<span style=\"color: #e63946;\">");
                    for (String name : names) {
                        noticeContent.append(name + "、");
                    }
                    noticeContent.deleteCharAt(noticeContent.length() - 1);
                    noticeContent.append("</span>的数据<span style=\"color: #e63946;\">");
                    noticeContent.append(warnTime);
                    switch (warnTimeType) {
                        case "0":
                            noticeContent.append("小时后");
                            break;
                        case "1":
                            noticeContent.append("天后");
                            break;
                        case "2":
                            noticeContent.append("周后");
                            break;
                    }
                    noticeContent.append("</span>将被回收，届时将无法捞取,请注意筛查避免有用的数据被回收</p>");
                    sysNotice.setNoticeContent(noticeContent.toString());
                    sysNotice.setStatus("0");
                    sysNotice.setCreateTime(LocalDateTime.now());
                    noticeMapper.insert(sysNotice);
                    flag = true;
                }
            }
        }
        if (flag) {
            log.info("开始调用WebSocket向前端发送消息");
        }
    }

}
